﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.Runtime.CompilerServices;

namespace GoogleFinance
{
    /// <summary>
    /// An object that is responsible for remote API requests against Google Finance
    /// </summary>
    public class StockQuotes
    {
        /// <summary>
        /// The address of the google finance rest api
        /// </summary>
        private const string FinanceRestServiceUrl = "www.google.com/ig/api";

        /// <summary>
        /// Gets the <see cref="XmlDocument"/> from the data service and parses all nodes
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url"></param>
        /// <param name="symbols"></param>
        /// <returns></returns>
        private IList<T> GetFinanceStockXmlResponse<T>(string url, string[] symbols) where T : IXmlNodeParsable, new()
        {
            XmlDocument doc = GetXmlDocumentFromUri(new Uri(url));
            XmlNodeList nodes = doc.SelectNodes("/xml_api_reply/finance");
            List<T> items = new List<T>();
            foreach (XmlNode node in nodes)
            {
                T obj = new T();
                IXmlNodeParsable parsable = obj;
                parsable.Parse(node);
                items.Add(obj);
            }
            return items;
        }

        private XmlDocument GetXmlDocumentFromUri(Uri uri)
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
            webRequest.Accept = "text/xml";
            using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
            using (System.IO.StreamReader responseStream = new System.IO.StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(responseStream);
                return doc;
            }
        }

        /// <summary>
        /// Returns a list of StockQuote objects for the supplied symbols
        /// </summary>
        /// <param name="symbols">The comma separated exchange symbols to return (e.g. LLOY.D,RBS.L)</param>
        /// <returns></returns>
        public IList<StockQuote> GetQuotesForSymbols(string[] symbols)
        {
            UrlBuilder url = new UrlBuilder(FinanceRestServiceUrl);
            symbols.ToList().ForEach(s => url.AddQuery("stock", s));
            return GetFinanceStockXmlResponse<StockQuote>(url.ToString(), symbols);
        }
    }
}
